home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / SimpleViewer / SimpleViewer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-20  |  26.7 KB  |  1,094 lines  |  [TEXT/MPCC]

  1. //--------------------------------------------------------------------------------------------
  2. // simple viewer application 
  3. // DEVELOPER SUPPORT May 95
  4. //
  5. // This is a simple viewer application, that illustrates a minimal, but
  6. // functionally complete viewer application.
  7. //
  8. // Nick Thompson, Developer Support, Apple Computer (DEVSUPPORT),
  9. // ©1995, Apple Computer Inc., All Rights Reserved
  10.  
  11. #include <AppleEvents.h>
  12. #include <menus.h>
  13. #include <PictUtil.h>
  14. #include <QDOffScreen.h>
  15. #include <Errors.h>
  16.  
  17. #include "QD3DViewer.h"
  18.  
  19. //--------------------------------------------------------------------------------------------
  20. //
  21. const int    kWindowWidth = 220 ;
  22. const int    kWindowHeight = 150 ;
  23.  
  24. //--------------------------------------------------------------------------------------------
  25. //
  26. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  27. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  28.  
  29.     
  30.  
  31. //--------------------------------------------------------------------------------------------
  32. // menu id's
  33. enum {
  34.     mApple = 128,
  35.     mFile,
  36.     mEdit
  37. } ;
  38.  
  39. //--------------------------------------------------------------------------------------------
  40. // command id's, Apple menu
  41. enum {
  42.     iAbout = 1
  43. } ;
  44.  
  45. //--------------------------------------------------------------------------------------------
  46. // command id's, File menu
  47. enum {
  48.     iNew = 1,
  49.     iOpen,
  50.     iUnused1,
  51.     iClose,
  52.     iSave,
  53.     iSaveAs,
  54.     iRevert,
  55.     iUnused2,
  56.     iQuit
  57. } ;
  58.  
  59. //--------------------------------------------------------------------------------------------
  60. // command id's, Edit menu
  61. enum {
  62.     iUndo = 1,
  63.     iUnused3,
  64.     iCut,
  65.     iCopy,
  66.     iPaste,
  67.     iClear
  68. } ;
  69.  
  70. //--------------------------------------------------------------------------------------------
  71. // static control variables
  72.  
  73. static Boolean gQuitFlag = false ;                // we ain't quittin yet
  74. static Point gStaggerPos = {50,50} ;            // start opening staggered windows at this point
  75. static AEAddressDesc    gSelfAddress;            // A self-addressed address descriptor record
  76. static ProcessSerialNumber    gSelfPSN;            // This application's psn
  77.  
  78. //--------------------------------------------------------------------------------------------
  79. // function prototypes
  80.  
  81. Boolean SupportsQuickDraw3D(void) ;
  82. Boolean     SupportsQuickDraw3DViewer(void) ;
  83. void         InitToolbox( void ) ;
  84. void        FailIfErr(OSErr something ) ;
  85. void         MainEventLoop( void ) ;
  86. void         HandleKeyPress( EventRecord *event ) ;
  87. Boolean        HandleEvent( EventRecord *theEvent ) ;
  88. void         HandleMenuCommand( long menuResult ) ;
  89. void         MyAdjustMenus( void ) ;
  90. OSErr        MyDisposeViewerWindow( WindowPtr theWindow ) ;
  91. CGrafPtr     MyCreateViewerWindow( void ) ;
  92.  
  93. //-- AppleEvent Related
  94.  
  95. Boolean SupportsAEVT(void) ;
  96. void RegisterMyEvents(void) ;
  97. pascal OSErr MyAEHandleOAPP( AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) ;
  98. pascal OSErr MyAEHandleODOC(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon) ;
  99. pascal OSErr MyAEHandlePDOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon) ;
  100. pascal OSErr MyAEHandleQUIT(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon) ;
  101. void DoAppOpenCommand( void ) ;
  102. void MySendQuitApp( void ) ;
  103. void MySendOpenDoc(FSSpec *myFSSpec) ;
  104.  
  105. //--------------------------------------------------------------------------------------------
  106. // Constants
  107.  
  108. const RGBColor    kRGBBlack = { 0x0000, 0x0000, 0x0000 } ;
  109. const RGBColor    kRGBWhite = { 0xFFFF, 0xFFFF, 0xFFFF } ;
  110. const int         kMyAboutDialogID = 128 ;
  111. const int         kMyFatalDialogID = 129 ;
  112. const int        kQD3DAlertID = 27309 ;
  113. //--------------------------------------------------------------------------------------------
  114. // Types
  115. typedef struct _viewerData {
  116.     TQ3ViewerObject        theViewer ;
  117.     FSSpec                theFile ;
  118.     Boolean                isFileValid ;
  119. } ViewerData, *ViewerDataPtr, **ViewerDataHandle ;
  120.  
  121. //--------------------------------------------------------------------------------------------
  122. //
  123. //
  124.  
  125. void main()
  126. {
  127.     MoreMasters(); MoreMasters() ; MoreMasters() ;
  128.     MaxApplZone() ;            // Maximise the heap - the viewer requires at least 32k
  129.     InitToolbox() ;
  130.  
  131.     // WE DON'T CHECK FOR 68K machine.
  132.     // Instead I use the NotPPC.rsrc resource file.  This is a file with a 68k CODE 0
  133.     // and CODE 1 resource that puts up a dialog that says "this app only runs on a power
  134.     // macintosh computer.
  135.     
  136.     if( SupportsAEVT() && SupportsQuickDraw3D() && SupportsQuickDraw3DViewer()) {
  137.         // AppleEvent stuff:
  138.         // Set up the self-addressed descriptor record.
  139.          gSelfPSN.highLongOfPSN = 0;
  140.          gSelfPSN.lowLongOfPSN = kCurrentProcess;        //* Use this instead of GetCurrentProcess *//
  141.          FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&gSelfPSN,sizeof(ProcessSerialNumber),&gSelfAddress));
  142.  
  143.         RegisterMyEvents() ;    // register the appleevents for this app
  144.  
  145.         MainEventLoop() ;        // Handle events 'til we die
  146.     } 
  147.     else {
  148.         Str255 theString ;
  149.         GetIndString(theString,kQD3DAlertID,3);
  150.         ParamText( theString, 0L,  0L,  0L ) ;
  151.         (void)Alert(kQD3DAlertID,nil);
  152.     }
  153. }
  154. //---------------------------------------------------------------------
  155.  
  156. Boolean SupportsQuickDraw3D(void) 
  157. {
  158.     OSErr err;
  159.     long response;
  160.         
  161.     err = Gestalt(gestaltQD3D,&response);
  162.     if (err!=noErr)
  163.         return false;
  164.         
  165.     return (response && (response << gestaltQD3DAvailable));
  166. }
  167.  
  168. //---------------------------------------------------------------------
  169.  
  170. Boolean SupportsQuickDraw3DViewer(void) 
  171. {
  172.     OSErr err;
  173.     long response;
  174.         
  175.     err = Gestalt( gestaltQD3DViewer,&response );
  176.     if (err!=noErr)
  177.         return false;
  178.         
  179.     return (response && ( response << gestaltQD3DViewerAvailable ));
  180. }
  181.  
  182. //--------------------------------------------------------------------------------------------
  183. //
  184. //
  185. void FailIfErr( OSErr something )
  186.     OSErr myErr ; 
  187.     if(( myErr = something) != noErr ) { 
  188.         ModalFilterUPP         theProc ;
  189.         DialogPtr            theDialog ; 
  190.         short                itemHit ;
  191.         Str255                theError ;
  192.         
  193.         NumToString(something,theError);
  194.     
  195.         theDialog = GetNewDialog ( kMyFatalDialogID, nil, (WindowPtr)-1 );
  196.         
  197.         // these two lil' snappers are system 7 only
  198.         // so if you use them, check before!!
  199.         // in this app we will only run on Power
  200.         // Macintosh, so we don't check
  201.         
  202.         GetStdFilterProc( &theProc ) ;
  203.         SetDialogDefaultItem(theDialog, ok) ;
  204.         
  205.         ParamText( theError, 0L, 0L, 0L ) ;
  206.         
  207.         // put the dialog up and loop 'til
  208.         // the user hits the OK button
  209.  
  210.         do {
  211.             ModalDialog ( theProc, &itemHit );
  212.         } while( itemHit != ok ) ;
  213.         
  214.         DisposeDialog ( theDialog );
  215.         
  216.         ExitToShell() ; 
  217.     } 
  218.  
  219. //--------------------------------------------------------------------------------------------
  220. //
  221. //
  222.  
  223. void InitToolbox()
  224. {
  225.     Handle        menuBar = nil;
  226.  
  227.  
  228.     InitGraf((Ptr) &qd.thePort);
  229.     InitFonts();
  230.     InitWindows();
  231.     InitMenus();
  232.     TEInit();
  233.     InitDialogs((long)nil);
  234.     InitCursor();
  235.  
  236.     // initialize application globals
  237.     
  238.     gQuitFlag = false;
  239.     
  240.     
  241.     menuBar = GetNewMBar(128);                // Read menus into menu bar, MBAR res id is 128
  242.     
  243.     if ( menuBar == nil )
  244.          ExitToShell();                        // if we dont have it then quit - your app 
  245.                                              // needs a dialog here
  246.  
  247.     SetMenuBar(menuBar);                    // Install menus
  248.     DisposeHandle(menuBar);
  249.     
  250.     AppendResMenu(GetMenuHandle(mApple), 'DRVR');    // Add DA names to Apple menu, ID 128
  251.  
  252.     MyAdjustMenus() ;
  253.     DrawMenuBar();
  254. }
  255.  
  256.  
  257. //--------------------------------------------------------------------------------------------
  258. //
  259. //
  260. void MainEventLoop()
  261. {
  262.     EventRecord         event;
  263.     WindowPtr           theWindow;
  264.     Boolean                wasViewerEvent ;
  265.     GrafPtr             savedPort ;
  266.     Point                localPt ;
  267.     TQ3ViewerObject     theViewer ;
  268.     ViewerDataHandle    myData ;
  269.  
  270.     MyAdjustMenus() ;
  271.     while( !gQuitFlag )
  272.     {
  273.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  274.         {
  275.             
  276.             if((theWindow = FrontWindow()) != nil ) {
  277.             
  278.                 myData = (ViewerDataHandle)GetWRefCon(theWindow);
  279.                 theViewer = (**myData).theViewer;
  280.             }
  281.             
  282.             if( theViewer ) {
  283.                 GetPort( &savedPort ) ;
  284.                 SetPort( (GrafPtr)theWindow ) ;
  285.                 GetMouse(&localPt);
  286.                 if (!Q3ViewerAdjustCursor(theViewer, &localPt))
  287.                     InitCursor();
  288.                 wasViewerEvent = Q3ViewerEvent ( theViewer, &event );
  289.                 SetPort( savedPort ) ;
  290.             }
  291.             else
  292.                 wasViewerEvent = false ;
  293.             
  294.             // was it a viewer event????
  295.             if( !wasViewerEvent )
  296.                 HandleEvent( &event );
  297.         }
  298.     }
  299. }
  300.  
  301. //----------------------------------------------------------------------------------
  302. //    HandleActivateWindow is called when an event is received that reports that
  303. //    a window is being either activated or deactivated.
  304.  
  305. static void HandleActivateWindow(WindowPtr theWindow, short activate)
  306. {
  307.     if (theWindow) {
  308.         if (activate) {
  309.         
  310.             // do whatever else you'd like to do for a activate event
  311.             LoadScrap() ;
  312.  
  313.         } else {
  314.         
  315.             // do whatever you'd like to do for a deactivate event
  316.             UnloadScrap() ;
  317.         }
  318.     }
  319. }
  320.  
  321. //--------------------------------------------------------------------------------------------
  322. //
  323. //
  324. Boolean        HandleEvent( EventRecord *theEvent )
  325. {
  326.     short               thePart;
  327.     WindowPtr            theWindow ;
  328.     Rect                screenRect;
  329.     GrafPtr                oldPort ;
  330.     Point                aPoint = {100, 100};
  331.     TQ3ViewerObject     theViewer ;
  332.     ViewerDataHandle    myData ;
  333.     
  334.     switch (theEvent->what) {
  335.         case mouseDown:
  336.         
  337.             thePart = FindWindow( theEvent->where, &theWindow );
  338.             
  339.             switch( thePart ) {
  340.                 case inMenuBar: 
  341.                     MyAdjustMenus() ;
  342.                     HandleMenuCommand(MenuSelect(theEvent->where));
  343.                     break;
  344.                 
  345.                 case inDrag:
  346.                     screenRect = (**GetGrayRgn()).rgnBBox;
  347.                     DragWindow( theWindow, theEvent->where, &screenRect );
  348.                     break ;
  349.             
  350.                 case inContent:
  351.                     if (theWindow != FrontWindow())
  352.                         SelectWindow( theWindow );
  353.                     break ;
  354.             
  355.                 case inGoAway:
  356.                     if (TrackGoAway( theWindow, theEvent->where )) {
  357.                         MyDisposeViewerWindow( theWindow ) ;
  358.                     }
  359.                     break ;
  360.                     
  361.                 default:
  362.                     break ;
  363.             }
  364.             break ;
  365.                     
  366.                 
  367.         case updateEvt:
  368.         
  369.             theWindow = (WindowPtr)theEvent->message;
  370.             myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  371.             theViewer = (**myData).theViewer ;
  372.             
  373.             GetPort(&oldPort ) ;    
  374.             SetPort( theWindow );
  375.             
  376.             BeginUpdate( theWindow );
  377.             Q3ViewerDraw( theViewer ) ;
  378.             EndUpdate( theWindow );
  379.             
  380.             SetPort( oldPort ) ;
  381.             
  382.             break ;
  383.             
  384.         case keyDown:
  385.         case autoKey:
  386.             HandleKeyPress(theEvent);
  387.             break;
  388.             
  389.         case diskEvt:
  390.             if ( HiWrd(theEvent->message) != noErr ) 
  391.                 (void) DIBadMount(aPoint, theEvent->message);
  392.             break;
  393.             
  394.         case osEvt:
  395.             break ;
  396.         case activateEvt:
  397.             if ((theWindow = (WindowPtr) theEvent->message) != nil) {
  398.                 HandleActivateWindow(theWindow, (theEvent->modifiers & activeFlag));
  399.             }
  400.  
  401.             break;
  402.  
  403.         case kHighLevelEvent:                        // Let the Apple Event Manager handle high level event.
  404.             AEProcessAppleEvent(theEvent);
  405.             break;
  406.  
  407.     }
  408.     return true ;
  409. }
  410.  
  411.  
  412. //--------------------------------------------------------------------------------------------
  413. //
  414. //
  415. void HandleKeyPress(EventRecord *event)
  416. {
  417.     char    key;
  418.  
  419.     key = event->message & charCodeMask;
  420.     
  421.     // just check to see if we want to quit...
  422.     
  423.     if ( event->modifiers & cmdKey ) {        /* Command key down? */
  424.         HandleMenuCommand(MenuKey(key));
  425.     } 
  426. }
  427.  
  428. //--------------------------------------------------------------------------------------------
  429. //
  430. //
  431.  
  432. static void HandleAboutApp( void )
  433. {
  434.     ModalFilterUPP         theProc ;
  435.     DialogPtr            theDialog ; 
  436.     short                itemHit ;
  437.  
  438.     theDialog = GetNewDialog ( kMyAboutDialogID, nil, (WindowPtr)-1 );
  439.     
  440.     // these two lil' snappers are system 7 only
  441.     // so if you use them, check before!!
  442.     // in this app we will only run on Power
  443.     // Macintosh, so we don't check
  444.     
  445.     GetStdFilterProc( &theProc ) ;
  446.     SetDialogDefaultItem(theDialog, ok) ;
  447.     
  448.     // put the dialog up and loop 'til
  449.     // the user hits the OK button
  450.     
  451.     do {
  452.         ModalDialog ( theProc, &itemHit );
  453.     } while( itemHit != ok ) ;
  454.     
  455.     DisposeDialog ( theDialog );
  456. }
  457.  
  458. //--------------------------------------------------------------------------------------------
  459. //
  460. //
  461. static OSErr HandleOpenDoc(FSSpec *theFile)
  462. {
  463.     OSErr                err ;
  464.     short                theRef ;
  465.     ViewerDataHandle    myData ;
  466.     TQ3ViewerObject     theViewer ;
  467.     WindowPtr            theWindow ;
  468.  
  469.     // display the contents
  470.     theWindow = (WindowPtr)MyCreateViewerWindow() ;
  471.     
  472.     // open the file
  473.     err = FSpOpenDF( theFile, fsRdPerm, &theRef ) ;
  474.     if (err == noErr)
  475.     {
  476.         myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  477.         theViewer = (**myData).theViewer ;
  478.         (**myData).theFile = *theFile ;
  479.         (**myData).isFileValid = true ;
  480.         Q3ViewerUseFile(theViewer, theRef) ;
  481.         err = FSClose(theRef) ;
  482.     }
  483.     
  484.     // set the window title
  485.     SetWTitle( theWindow, theFile->name );
  486.     MyAdjustMenus() ;
  487.     return err ;
  488. }
  489.  
  490.  
  491. //--------------------------------------------------------------------------------------------
  492. //
  493. //
  494. void HandleMenuCommand(long menuResult)
  495. {
  496.     short                menuID;
  497.     short                menuItem;
  498.     Str255                daName;
  499.     
  500.  
  501.     short                numTypes = 2 ;
  502.     SFTypeList            myTypes = { '3DMF', 'TEXT', 0 } ;
  503.     OSErr                err ;
  504.     short                theRef ;
  505.     
  506.     ViewerDataHandle    myData ;
  507.     TQ3ViewerObject     theViewer ;
  508.     WindowPtr            theWindow ;
  509.     GrafPtr                savedPort ;
  510.     
  511.     FSSpec                theFile ;
  512.         
  513.     StandardFileReply    theSFReply ;
  514.  
  515.     menuID = HiWrd(menuResult);
  516.     menuItem = LoWrd(menuResult);
  517.     
  518.     switch ( menuID ) {
  519.         //
  520.         //--------------------------------------------------------------------------    
  521.         //
  522.         case mApple:
  523.             switch ( menuItem ) {
  524.  
  525.                 case iAbout:
  526.                     HandleAboutApp() ;    
  527.                     break ;
  528.                                 
  529.                 default:
  530.                     GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
  531.                     (void) OpenDeskAcc(daName);
  532.                     break;
  533.             }
  534.             break;
  535.         //
  536.         //--------------------------------------------------------------------------    
  537.         //
  538.         case mFile:
  539.             switch ( menuItem ) {
  540.                 case iNew:
  541.                     // display the contents
  542.                     (void)MyCreateViewerWindow() ;
  543.                     break ;
  544.                 
  545.                 case iOpen:
  546.                     // Get the file name to open
  547.                     StandardGetFile( nil, numTypes, myTypes, &theSFReply ) ;
  548.                     
  549.                     // did the user cancel, if not open the file?
  550.                     if(theSFReply.sfGood)
  551.                         MySendOpenDoc(&theSFReply.sfFile) ;
  552.  
  553.                     break ;
  554.                     
  555.                     
  556.                 case iRevert:
  557.                 
  558.                     // we know this can't be called as long as there
  559.                     // is an app window open (MyAdjustMenus) so get the refcon
  560.                     // from the front window and get the FSSpec from that
  561.                     theWindow = FrontWindow() ;
  562.                     myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  563.                     theFile = (**myData).theFile ;
  564.                     
  565.                     // open the file and read it back into the viewer
  566.                     err = FSpOpenDF( &theFile, fsRdPerm, &theRef ) ;
  567.                     if (err == noErr)
  568.                     {
  569.                         theViewer = (**myData).theViewer ;
  570.                         Q3ViewerUseFile(theViewer, theRef) ;
  571.                         err = FSClose(theRef) ;
  572.                     }
  573.                     GetPort( &savedPort ) ;
  574.                     SetPort((GrafPtr)theWindow) ;
  575.                     InvalRect( &theWindow->portRect ) ;
  576.                     SetPort( savedPort ) ;
  577.                     break ;        
  578.                             
  579.                 case iSave:                
  580.                 
  581.                     // we know this can't be called as long as there
  582.                     // is an app window open (MyAdjustMenus) so get the refcon
  583.                     // from the front window and get the FSSpec from that
  584.                     theWindow = FrontWindow() ;
  585.                     myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  586.                     theFile = (**myData).theFile ;
  587.                     theViewer = (**myData).theViewer ;
  588.  
  589.                     // assumes the original file still exists
  590.                     err = FSpOpenDF(&theFile, fsWrPerm, &theRef);
  591.                     if (err == noErr)
  592.                     {
  593.                         Q3ViewerWriteFile(theViewer, theRef);
  594.                         err = FSClose(theRef);
  595.                     }
  596.                     break ;
  597.                 
  598.                 case iSaveAs:
  599.                     // we know this can't be called as long as there
  600.                     // is an app window open (MyAdjustMenus) so get the refcon
  601.                     // from the front window and get the FSSpec from that
  602.                     theWindow = FrontWindow() ;
  603.                     myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  604.                     theViewer = (**myData).theViewer ;
  605.  
  606.                     StandardPutFile("\pSave model as:", "\pUntitled", &theSFReply);
  607.                     if (theSFReply.sfGood)
  608.                     {
  609.                         err = FSpOpenDF(&theSFReply.sfFile, fsWrPerm, &theRef);
  610.                         if (err != noErr)
  611.                         {
  612.                             err = FSpCreate(&theSFReply.sfFile, '????', '3DMF', theSFReply.sfScript);
  613.                             if (err == noErr)
  614.                                 err = FSpOpenDF(&theSFReply.sfFile, fsCurPerm, &theRef);
  615.                         }
  616.                         if (err == noErr)
  617.                         {
  618.                             Q3ViewerWriteFile(theViewer, theRef);
  619.                             err = FSClose(theRef);
  620.                         }
  621.                         
  622.                         // set up our record of the file location,
  623.                         // update the structure
  624.                         theWindow = FrontWindow() ;
  625.                         myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  626.                         theViewer = (**myData).theViewer ;
  627.                         (**myData).theFile = theSFReply.sfFile ;
  628.                         (**myData).isFileValid = true ;
  629.                         
  630.                         // reset the window title
  631.                         SetWTitle( theWindow, theSFReply.sfFile.name );
  632.                     }
  633.                     break;                
  634.                 
  635.                 case iClose:
  636.                     MyDisposeViewerWindow ( FrontWindow() );
  637.                     break ;
  638.                     
  639.                 case iQuit:
  640.                     MySendQuitApp();
  641.                     break;
  642.             }
  643.             break;
  644.             
  645.             
  646.         //
  647.         //--------------------------------------------------------------------------    
  648.         //
  649.         case mEdit:
  650.             // display the contents
  651.             theWindow = FrontWindow() ;
  652.             myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  653.             theViewer = (**myData).theViewer ;
  654.             switch(menuItem)
  655.             {
  656.                 case iCut:
  657.                     Q3ViewerCut(theViewer);
  658.                     break;
  659.                 case iCopy:
  660.                     Q3ViewerCopy(theViewer);
  661.                     break;
  662.                 case iPaste:
  663.                     Q3ViewerPaste(theViewer);
  664.                     break;
  665.                 case iClear:
  666.                     Q3ViewerClear(theViewer);
  667.                     break;
  668.                 default:
  669.                     break;
  670.             }
  671.             break; 
  672.  
  673.     }
  674.     HiliteMenu(0);        // Unhighlight whatever MenuSelect or MenuKey hilited
  675. }
  676.  
  677. //--------------------------------------------------------------------------------------------
  678. //
  679. //
  680. void MyAdjustMenus( void ) 
  681. {
  682.     WindowPtr            theWindow ;
  683.     ViewerDataHandle    myData ;
  684.     MenuHandle            theMenu ;
  685.  
  686.     theWindow = FrontWindow() ;
  687.     
  688.     
  689.     if( theWindow != nil ) {
  690.     
  691.         theMenu =  GetMenuHandle ( mFile ) ;
  692.         
  693.         EnableItem ( theMenu, iClose );
  694.         EnableItem ( theMenu, iSaveAs );
  695.                  
  696.         myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  697.         
  698.          if(    (**myData).isFileValid) {
  699.             EnableItem ( theMenu, iSave );
  700.             EnableItem (theMenu, iRevert );
  701.          }
  702.          else {
  703.             DisableItem ( theMenu, iSave );
  704.             DisableItem ( theMenu, iRevert );
  705.          
  706.          }
  707.          
  708.          EnableItem ( GetMenuHandle ( mEdit ), 0 );
  709.  
  710.     }
  711.     else {
  712.  
  713.         theMenu =  GetMenuHandle ( mFile ) ;
  714.  
  715.         DisableItem ( theMenu, iClose );
  716.         DisableItem ( theMenu, iRevert );
  717.         DisableItem ( theMenu, iSave );
  718.         DisableItem ( theMenu, iSaveAs );
  719.         
  720.         DisableItem ( GetMenuHandle ( mEdit ), 0 );
  721.     }
  722.     
  723.     // we don't support undo
  724.     DisableItem ( GetMenuHandle ( mEdit ), iUndo );
  725.     
  726.     DrawMenuBar() ;
  727. }
  728.  
  729.  
  730. //--------------------------------------------------------------------------------------------
  731. //
  732. //
  733. OSErr    MyDisposeViewerWindow( WindowPtr theWindow )
  734. {
  735.     TQ3ViewerObject     theViewer ;
  736.     ViewerDataHandle    myData ;
  737.     
  738.     if( theWindow == nil)
  739.         return paramErr ;
  740.  
  741.     myData = (ViewerDataHandle)GetWRefCon( theWindow ) ;
  742.     theViewer = (**myData).theViewer ;
  743.     
  744.     DisposeHandle((Handle)myData);
  745.     DisposeWindow(theWindow);
  746.     
  747.     MyAdjustMenus() ;
  748.     return     Q3ViewerDispose(theViewer);
  749. }
  750.  
  751.  
  752. //--------------------------------------------------------------------------------------------
  753. //
  754. //
  755. CGrafPtr MyCreateViewerWindow(  )
  756. {
  757.  
  758.     Rect                theRect ;
  759.     GrafPtr                savedPort ;
  760.     TQ3ViewerObject        myViewerObj ;
  761.     WindowPtr            theWindow ;
  762.     ViewerDataHandle    myData = (ViewerDataHandle)NewHandle(sizeof(ViewerData)) ;
  763.     
  764.     GetPort( &savedPort ) ;
  765.         
  766.     // set the new rect up with a stagger for multiple windows
  767.     SetRect(    &theRect, 
  768.                 gStaggerPos.h, 
  769.                 gStaggerPos.v, 
  770.                 gStaggerPos.h + kWindowWidth, 
  771.                 gStaggerPos.v + kWindowHeight );
  772.  
  773.     gStaggerPos.h += 16 ;
  774.     gStaggerPos.v += 16 ;        // this is not "real staggering code, it don't wrap ;        
  775.                          
  776.     theWindow  = NewCWindow(    nil, 
  777.                                 &theRect, 
  778.                                 "\pUntitled", 
  779.                                 false, 
  780.                                 documentProc, 
  781.                                 (WindowPtr)-1, 
  782.                                 true, 
  783.                                 0L );    
  784.                     
  785.     SetPort( (GrafPtr)theWindow ) ;
  786.     
  787.     // set up the viewer object here
  788.     myViewerObj = Q3ViewerNew ((CGrafPtr)theWindow,  &theWindow->portRect,  kQ3ViewerDefault) ; 
  789.     
  790.     //stuff the reference to the viewer in the RefCon field of the Window
  791.     (**myData).theViewer = myViewerObj ;
  792.     (**myData).isFileValid = false ;
  793.     SetWRefCon( theWindow, (long)myData );
  794.     
  795.     // make sure it is visible
  796.     ShowWindow( theWindow ) ;
  797.     
  798.     // invalidate the content region of the window - 
  799.     // we don't do any drawing to it here.
  800.     InvalRect ( &theRect );
  801.     SetPort( savedPort ) ;
  802.     
  803.     return (CGrafPtr)theWindow ;
  804. }
  805.  
  806.  
  807. //-----------------------------------------------------------------------
  808. // returns true if the platform supports appleevents - we won't run
  809. // if it doesn't
  810.  
  811. Boolean SupportsAEVT(void)
  812. {
  813.     OSErr err;
  814.     long response;
  815.         
  816.     err = Gestalt(gestaltAppleEventsAttr,&response);
  817.     if (err!=noErr)
  818.         return false;
  819.         
  820.     return (response && (response << gestaltAppleEventsPresent));
  821. }
  822.  
  823. //-----------------------------------------------------------------------
  824. // called to register our appleevent handlers
  825.  
  826. void RegisterMyEvents(void)
  827. {
  828.     OSErr err;
  829.     
  830.     if (!SupportsAEVT())
  831.         return;
  832.     
  833.     err = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,NewAEEventHandlerProc(MyAEHandleOAPP),0L,false);
  834.     if (err!=noErr)
  835.         return;
  836.                 
  837.     err = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,NewAEEventHandlerProc(MyAEHandleODOC),0L,false);
  838.     if (err!=noErr)
  839.         return;
  840.                 
  841.     err = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,NewAEEventHandlerProc(MyAEHandlePDOC),0L,false);
  842.     if (err!=noErr)
  843.         return;
  844.                 
  845.     err = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,NewAEEventHandlerProc(MyAEHandleQUIT),0L,false);
  846.     if (err!=noErr)
  847.         return;
  848. }
  849.  
  850. //-----------------------------------------------------------------------
  851. // open application event handler for the core event suite, 
  852. // by default we just want a blank new document
  853.  
  854. pascal OSErr MyAEHandleOAPP( AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
  855. {
  856.     // we don't actually do anything on open - you could,
  857.     // for example you might want to open a blank untitled 
  858.     // window
  859.     
  860. #pragma unused (theAppleEvent, reply, refCon)
  861.     OSErr err = noErr ;
  862.     return err;
  863. }
  864.  
  865.  
  866. //-----------------------------------------------------------------------
  867. // handler for the open document appleevent handler
  868.  
  869. pascal OSErr MyAEHandleODOC(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
  870. {
  871. #pragma unused ( reply, refCon )
  872.     FSSpec         myFSS;
  873.     AEDescList    docList;
  874.     OSErr        err,
  875.                 ignoreErr;
  876.     long        index,
  877.                 itemsInList;
  878.     Size         actualSize;
  879.     AEKeyword    keywd;
  880.     DescType    returnedType;
  881.  
  882.     
  883.     err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList);
  884.     if (err == noErr) {
  885.     
  886.         // see how many descriptor items are in the list
  887.         // this is the number of documents we want to open
  888.         err = AECountItems(&docList,&itemsInList);
  889.  
  890.         // now get each descriptor record from the list
  891.         // coerce the returned data to an FSSpec record, and
  892.         // open the asoociated file
  893.         
  894.         for (index=1; index <= itemsInList && err == noErr; index++) {
  895.         
  896.             err = AEGetNthPtr(    &docList, 
  897.                                 index,
  898.                                 typeFSS,
  899.                                 &keywd,
  900.                                 &returnedType,
  901.                                 (Ptr)&myFSS,
  902.                                 sizeof(myFSS),
  903.                                 &actualSize);
  904.     
  905.             if (err == noErr)    {
  906.             
  907.                 FInfo        fndrInfo ;
  908.                 
  909.                 // we now have a valid FSSpec to reference the file, we need to know 
  910.                 // what type the file is to determine which file open function to call
  911.                 // we can determine this from the finder info for the file
  912.                 
  913.                 err = FSpGetFInfo( &myFSS, &fndrInfo );    
  914.                 
  915.                 // if we got that ok, then we switch on the file  
  916.                 // type (we don't care about the creator type)    
  917.                         
  918.                 if (err == noErr)    {
  919.                 
  920.                     switch( fndrInfo.fdType ) {
  921.                         case 'TEXT':
  922.                         case '3DMF':
  923.                             err =  HandleOpenDoc(&myFSS);
  924.                             break ;
  925.                     }
  926.                 }
  927.             }
  928.         }
  929.         ignoreErr = AEDisposeDesc(&docList);
  930.     }
  931.     return err ;
  932. }
  933.  
  934. //-----------------------------------------------------------------------
  935. // handler for the print document event handler
  936.  
  937. pascal OSErr MyAEHandlePDOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  938. {
  939. #pragma unused ( reply, refCon )
  940.     FSSpec         myFSS;
  941.     AEDescList    docList;
  942.     OSErr        err;
  943.     long        index,
  944.                 itemsInList;
  945.     Size         actualSize;
  946.     AEKeyword    keywd;
  947.     DescType    returnedType;
  948.  
  949.     
  950.     err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList);
  951.     if (err == noErr) {
  952.     
  953.         // see how many descriptor items are in the list
  954.         // this is the number of documents we want to open
  955.         err = AECountItems(&docList,&itemsInList);
  956.  
  957.         // now get each descriptor record from the list
  958.         // coerce the returned data to an FSSpec record, and
  959.         // open the asoociated file
  960.         
  961.         for (index=1; index <= itemsInList && err == noErr; index++) {
  962.         
  963.             err = AEGetNthPtr(    &docList, 
  964.                                 index,
  965.                                 typeFSS,
  966.                                 &keywd,
  967.                                 &returnedType,
  968.                                 (Ptr)&myFSS,
  969.                                 sizeof(myFSS),
  970.                                 &actualSize);
  971.     
  972.             if (err == noErr)    {                    
  973.                 // err = HandlePrintDoc( &myFSS );
  974.                 err = errAEEventNotHandled ;         // we don't do this yet...
  975.             }
  976.         }
  977.         err = AEDisposeDesc(&docList);
  978.     }
  979.     return err ;
  980. }
  981.  
  982. //-----------------------------------------------------------------------
  983. // quit appleevent handler
  984.  
  985. pascal OSErr MyAEHandleQUIT(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  986. {
  987. #pragma unused ( theAppleEvent, reply, refCon )
  988.     OSErr             err = noErr ;        // used as return value
  989.     WindowPtr        theWindow ;
  990.     Boolean            quitting = true ;
  991.  
  992.     
  993.     // close all windows and signal to Quit
  994.  
  995.         
  996.     // attempt to close all documents
  997.     while(( theWindow = FrontWindow()) != nil && quitting )
  998.         quitting = (MyDisposeViewerWindow( theWindow ) == noErr);    
  999.         
  1000.  
  1001.     // if we closed everything up successfully, we can return noErr, otherwise
  1002.     // indicate to sender of the 'quit' aevt that we canceled
  1003.     
  1004.     if (quitting) {
  1005.         gQuitFlag = true;                    // user didn't cancel
  1006.          AEDisposeDesc(&gSelfAddress);        // Dispose of my self-addressed descriptor.
  1007.     }
  1008.     else {
  1009.         err = userCanceledErr ;
  1010.     }
  1011.             
  1012.     return err ;
  1013. }
  1014.  
  1015.  
  1016. //----------------------------------------------------------------------------------//
  1017. //    Send a Quit Application Apple Event to myself to terminate this app.        
  1018.  
  1019. void MySendQuitApp( void )
  1020. {
  1021.     AppleEvent    myAppleEvent, reply;
  1022.     
  1023.     //    Create the Apple Event.
  1024.     FailIfErr(AECreateAppleEvent( kCoreEventClass, 
  1025.                                   kAEQuitApplication, 
  1026.                                   &gSelfAddress,
  1027.                                   kAutoGenerateReturnID, 
  1028.                                   kAnyTransactionID, 
  1029.                                   &myAppleEvent));
  1030.                                   
  1031.     //    Send the Apple Event.
  1032.       FailIfErr(AESend( &myAppleEvent, 
  1033.                         &reply, 
  1034.                         kAENoReply+kAENeverInteract, 
  1035.                         kAENormalPriority,
  1036.                         kAEDefaultTimeout, 
  1037.                         nil, 
  1038.                         nil));
  1039.                         
  1040.       AEDisposeDesc(&myAppleEvent);                // Dispose of the Apple Event.
  1041. } // MySendQuitApp
  1042.  
  1043.  
  1044. //----------------------------------------------------------------------------------//
  1045. //    Send a Open Document Application Apple Event to myself to open a document.        
  1046.  
  1047. void MySendOpenDoc(FSSpec *myFSSpec)
  1048. {
  1049.      AppleEvent    myAppleEvent;
  1050.     AppleEvent    defReply;
  1051.     AEDescList    docList;
  1052.     OSErr         ignoreErr;
  1053.     
  1054.     myAppleEvent.dataHandle = nil;
  1055.     docList.dataHandle  = nil;
  1056.     defReply.dataHandle = nil;
  1057.         
  1058.     // Create empty list and add one file spec
  1059.     FailIfErr(AECreateList(nil,0,false, &docList));
  1060.     
  1061.     FailIfErr(AEPutPtr(&docList,1,typeFSS,(Ptr)myFSSpec,sizeof(FSSpec)));
  1062.         
  1063.     FailIfErr(AECreateAppleEvent(    kCoreEventClass,
  1064.                                     kAEOpenDocuments,
  1065.                                     &gSelfAddress,
  1066.                                     kAutoGenerateReturnID,
  1067.                                     kAnyTransactionID,
  1068.                                     &myAppleEvent));
  1069.  
  1070.     // Put Params into our event and send it
  1071.  
  1072.     FailIfErr(AEPutParamDesc( &myAppleEvent,
  1073.                               keyDirectObject,
  1074.                               &docList));
  1075.  
  1076.     FailIfErr(AESend( &myAppleEvent,
  1077.                       &defReply,
  1078.                       kAENoReply+kAENeverInteract,
  1079.                       kAENormalPriority,
  1080.                       kAEDefaultTimeout,
  1081.                       nil,
  1082.                       nil));
  1083.         
  1084.         
  1085.     if (myAppleEvent.dataHandle) 
  1086.         ignoreErr = AEDisposeDesc(&myAppleEvent);
  1087.         
  1088.     if (docList.dataHandle) 
  1089.         ignoreErr = AEDisposeDesc(&docList);
  1090.             
  1091. }    // MySendOpenDoc 
  1092.